<?php namespace Model;

abstract Class Model {

	protected $db = null;

	public static function getFields() {
		return static::$fields;
	}

	public static function getForeignKeys() {
		return static::$foreignKeys;
	}

	public function setDB($db) {
		$this->db=$db;
	}

	public function __call($method, $arguments) {
		$model = get_called_class();
		$column = strtolower(substr($method, 6));
		$value = $arguments[0];
		if(isset($arguments[1])) {
			return $this->findAsoc($model,$column,$value,$arguments[1]);
		} else {
			return $this->findNoAsoc($model,$column,$value);
		}
	}

	public function findAll($arrayAsoc = null) {
		$model = get_called_class();
		if(isset($arrayAsoc)) {
			return $this->findAsoc($model, null, null, $arrayAsoc);
		} else {
			return $this->findNoAsoc($model);
		}
	}

	protected function findNoAsoc($model,$column=null,$value=null) {
		$table = substr(strtolower($model),6);
		$cond=null;
		if(isset($value)) {
			if(!is_numeric($value)) {
				$cond = $column . " LIKE " . "'%" . $value . "%'";
			} else {
				$cond = $column . "=" . $value;
			}
		}
		return $this->db->select($cond, null, $table);
	}

	protected function findAsoc($model,$column=null,$value=null,$tablesToJoin) {
		$table = substr(strtolower($model),6);
		$fieldsString = '';
		$tablesString = $table;
		if(isset($value)) {
			if(!is_numeric($value)) {
				$cond = $table.".".$column . " LIKE " . "'%" . $value . "%'";
			} else {
				$cond = $table.".".$column . "=" . $value;
			}
		} else {
			$cond = 'TRUE ';
		}
		foreach ($model::getFields() as $field) {
			$fieldsString .= ', ' . $table . '.' . $field . ' AS ' . $table . '1' . $field;
		}
		$foreignKeys = $model::getForeignKeys();
		if(isset($tablesToJoin)) {
			$tablesToJoin = array_flip($tablesToJoin);$foreignKeys = array_intersect_key($foreignKeys, $tablesToJoin);
		}
		foreach ($foreignKeys as $referencedTable => $fk) {
			$tablesString .= ', ' . $referencedTable;
			$referencedModel = 'Model\\'.ucfirst($referencedTable);
			foreach ($referencedModel::getFields() as $field) {
				$fieldsString .= ', ' . $referencedTable . '.' . $field . ' AS ' . $referencedTable . '1' . $field;
			}
			foreach ($fk as $localField => $referencedField) {
				$cond .= ' AND ' . $table . '.' . $localField . '=' . $referencedTable . '.' . $referencedField;
			}
		}
		$fieldsString = substr($fieldsString,2);
		$result = $this->db->select($cond, $fieldsString, $tablesString);
		$asocArrayResult = array();
		$index = 0;
		foreach ($result as $row) {
			foreach ($row as $field => $value) {
				$keyAndField = explode('1', $field);
				if (strpos($field, $table) === FALSE) {
					$asocArrayResult[$index][$keyAndField[0]][$keyAndField[1]] = $value;
				} else {
					$asocArrayResult[$index][$keyAndField[1]] = $value;
				}
			}
			$index++;
		}
		return $asocArrayResult;
	}

	protected function save($camposValores) {
			
		$model = get_called_class();
		$table = substr(strtolower($model),6);
		$stringCampos = "";
		$stringValores = "";
		foreach ($camposValores as $campo => $valor) {
			$stringCampos.= ','.$campo;
			!is_numeric($valor) ? $stringValores.= ",'".$valor."'" :
			$stringValores.= ','.$valor;
		}	
		$stringCampos = substr($stringCampos, 1);
		$stringValores = substr($stringValores, 1);
		if (!isset($camposValores['id'])) {	
			return $this->db->insert($stringCampos,$stringValores,$table);
		} else {
			$cond = 'id='.$camposValores['id'];
			unset($camposValores['id']);
			$this->db->update($camposValores,$cond,$table);
		}
	}
	
	protected function deleteById($id) {
		$model = get_called_class();
		$table = substr(strtolower($model),6);
		$cond = 'id='.$id;
		return $this->db->delete($cond,$table);
	}
}
